package net.vinote.smart.platform.service.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.Map;
import java.util.logging.Level;

import javax.servlet.http.HttpServletRequest;

import net.vinote.smart.platform.comm.PlatformConst;
import net.vinote.smart.platform.module.database.DBFactory;
import net.vinote.smart.platform.module.database.DBTransaction;
import net.vinote.smart.platform.module.log.RunLogger;
import net.vinote.smart.platform.service.HttpRequestPerform;
import net.vinote.smart.platform.service.SRE;
import net.vinote.smart.platform.service.util.Permission.PermissionUtil;

import org.apache.commons.lang.math.NumberUtils;
import org.json.JSONObject;

public class RunJavaMethod {

	public JSONObject runJavaMethod(HttpServletRequest request) {
		DBTransaction trans = null;
		JSONObject sReturn = new JSONObject();
		String runJava = request.getParameter("class").trim();
		String runMethod = request.getParameter("method");
		try {
			// 尝试充映射文件中查找
			int index = runJava.indexOf(".");
			Class<?> clazz = null;
			if (index > 0) {
				Map<String, String> actionMap = SRE.getActionMap(runJava
						.substring(0, index));
				if (actionMap != null) {
					try {
						clazz = Class.forName(actionMap.get(runJava
								.substring(index + 1)));
					} catch (Exception e) {
					}
				} else {
					clazz = Class.forName(runJava);
				}
			} else {
				clazz = Class.forName(runJava);
			}

			if (clazz == null) {
				RunLogger.getLogger().log(Level.WARNING, runJava);
				sReturn.put("success", false);
				sReturn.put("msg", "class is null");
				return sReturn;
			}
			Object obj = clazz.newInstance();
			// 是否为HttpRequestPerform请求
			String isPerfrom = request.getParameter("isHttpPerform");
			if (PlatformConst.YES.equals(isPerfrom)) {
				if (obj instanceof HttpRequestPerform) {
					HttpRequestPerform perform = (HttpRequestPerform) obj;
					String error = perform.validityCheck(request);
					if (error == null || error.length() == 0) {
						String data = ((HttpRequestPerform) obj)
								.perform(request);
						sReturn.put("success", true);
						sReturn.put("data", data);
					} else {
						sReturn.put("success", false);
						sReturn.put("msg", error);
					}
				} else {
					sReturn.put("success", false);
					sReturn.put("msg", "invalid HttpRequestPerform:" + clazz);
				}
				return sReturn;
			}

			// 自动填充request对象
			Field[] fields = clazz.getDeclaredFields();
			for (Field f : fields) {
				AutoInjection annotation = f.getAnnotation(AutoInjection.class);
				if (annotation == null) {
					continue;
				}
				f.setAccessible(true);
				Class<?> type = f.getType();
				if (type == HttpServletRequest.class) {
					f.set(obj, request);
				} else if (type == String.class) {
					f.set(obj, request.getParameter(f.getName()));
				} else if (type == int.class) {
					f.set(obj, NumberUtils.toInt(request.getParameter(f
							.getName())));
				} else {
					throw new UnsupportedOperationException(
							"RunJavaMethod unsupport to auto injection "
									+ type.getName() + " variable");
				}
			}

			boolean isTrans = PlatformConst.YES.equals(request
					.getParameter("isTrans"));// 是否使用事务
			Method method = null;
			if (isTrans) {
				trans = DBFactory.getFactory().getTransaction();
				try {
					method = clazz.getMethod(runMethod, DBTransaction.class);
					PermissionUtil.checkPerimission(method, request);// 权限校验
					String data = method.invoke(obj, trans).toString();
					sReturn.put("success", true);
					sReturn.put("data", data);
					trans.commit();
				} catch (Exception e) {
					trans.rollback();
					throw e;
				}
			} else {
				method = clazz.getMethod(runMethod);
				PermissionUtil.checkPerimission(method, request);// 权限校验
				String data = method.invoke(obj).toString();
				sReturn.put("success", true);
				sReturn.put("data", data);
			}
		} catch (InvocationTargetException e) {
			e.printStackTrace();
			sReturn.put("success", false);
			sReturn.put("msg", runJava + "." + runMethod + "():"
					+ e.getTargetException().getMessage());
		} catch (Exception e) {
			e.printStackTrace();
			sReturn.put("success", false);
			sReturn.put("msg",
					runJava + "." + runMethod + "():" + e.getLocalizedMessage());
		} finally {
			if (trans != null) {
				try {
					trans.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return sReturn;
	}
}
